package br.ufrj.dcc.tp.cliente.controller;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;

import br.ufrj.dcc.tp.cliente.gui.Options;
import br.ufrj.dcc.tp.cliente.gui.Window;
import br.ufrj.dcc.tp.cliente.model.Client;
import br.ufrj.dcc.tp.cliente.model.exception.ClientException;

public class ClientController implements ActionListener {
	
	private Client client;
	private Window window;
	private Options options;
	private TextAreaController textAreaController;
	private List<String> recipients;
	
	public ClientController() {
		this.textAreaController = new TextAreaController(this);
		this.window = new Window(this, textAreaController);
		this.options = new Options(this);
		this.client = new Client(this);
	}

	/** Envia a mensagem para o client. */
	public void sendMessage() {
		try {
			//Pega a mensagem da Window e pede para o Client enviar
			List<Integer> users = window.getRecipients();
			client.sendMessage(buildRecipients(users), window.getMessage());
			window.cleanUsers();
			window.cleanMessage();
		} catch(IOException e) {
			JOptionPane.showMessageDialog(null,"Erro ao tentar enviar mensagem ao servidor" , "Erro na conexão" , JOptionPane.ERROR_MESSAGE);
			options.setVisible(true);
			window.silentDispose();
			finish();
		}
	}
	
	/** Retorna o IP do servidor. */
	public String getServerIP() {
		String hostIP = options.getHostIP();
		if( hostIP.length() == 0 ) {
			return null;
		}
		return options.getHostIP();
	}
	
	/** Retorna a porta do servidor. */
	public Integer getServerPort() {
		return options.getHostPort();
	}
	
	public String getClientName() {
		String nome = options.getNome();
		if( nome.length() == 0 ) {
			return null;
		}
		return nome;
	}
	
	public void finish() {
		try {
			client.closeConnection();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/** Fecha a conexao cliente devido ao servidor. */
	public void serverDisconnected() {
		try {
			client.forceClose();
			JOptionPane.showMessageDialog(null,"Servidor Desconectou" , "Erro na conexão" , JOptionPane.INFORMATION_MESSAGE);
			options.setVisible(true);
			window.silentDispose();
		} catch( Exception e ) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(options.isYours(e.getSource())) {
			try {
				client.connectToServer();
				options.silentDispose();
				window.setVisible(true);
				window.setTitle(client.getClientName() + " Conectado!");
			} catch( ClientException ee ) {
				JOptionPane.showMessageDialog(null, ee.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE);
			} catch( IOException ee ) {
				// Erro na conexao.
				JOptionPane.showMessageDialog(null,"Erro ao tentar estabelecer conexão com o servidor" , "Erro na conexão" , JOptionPane.ERROR_MESSAGE);
			} catch (ClassNotFoundException ee) {
				// Erro na conexao.
				JOptionPane.showMessageDialog(null,"Erro ao tentar estabelecer conexão com o servidor" , "Erro na conexão" , JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	public void updateRecipientsList(List<String> recipients) {
		recipients.remove(client.getClientName());
		this.recipients = recipients;
		window.setRecipients(recipients);
	}
	
	public void appendMessage(String message) {
		window.appendMessage(message);
	}
	
	private List<String> buildRecipients(List<Integer> users) {
		List<String> recipients = new ArrayList<String>();
		for(Integer user : users) {
			recipients.add(this.recipients.get(user));
		}
		return recipients;
	}
	
	public Component getComponent( Class<? extends Component> klass ) {
		if( klass.isInstance(window) ) {
			return window;
		} else if( klass.isInstance(options) ) {
			return options;
		}
		
		return null;
	}
	
	public void forceStop() {
		finish();
		window.silentDispose();
		options.silentDispose();
	}
}
